Amazon API GatewayのHTTP APIをAuth0と統合して保護してみる
HTTP API は、低レイテンシーでコスト効率が良いAPIを提供するよう設計されていて、 OIDCとOAuth2.0認証をサポートしています。
オーソライザー | HTTP API | REST API |
---|---|---|
AWS Lambda | ✓ | ✓ |
IAM | ✓ | ✓ |
Amazon Cognito | ✓ | ✓ |
OpenID Connect/OAuth 2.0 | ✓ |
※ HTTP API および REST APIで使用できるオーソライザー
REST APIの場合はLambdaオーソライザーを使用してAuth0との統合が可能です。
HTTP APIの場合は、Lambdaオーソライザーが使用できないですが、OpenID Connect/OAuth 2.0の仕様に基づいて構築されたJWT(JSON Webトークン)オーソライザーを使うことにより認証と承認を処理できます。
アップデート により、HTTP APIでも Lambda, IAMがサポートされました。
以下のような構成です
やってみる
リソース
- API Gateway
- Lambda
- Auth0 API
AWSでAPIを構築
SAM(Serverless Application Model) を用いて構築します。
sam init
を実行しプロジェクトを作成します。
Quick Start Templates
を使用- runtimeは
nodejs12.x
- Project nameは任意のもの(default: sam-app)
- application templatesは
Hello World
$ sam init Which template source would you like to use? 1 - AWS Quick Start Templates 2 - Custom Template Location Choice: 1 Which runtime would you like to use? 1 - nodejs12.x 2 - python3.8 3 - ruby2.7 4 - go1.x 5 - java11 6 - dotnetcore3.1 7 - nodejs10.x 8 - python3.7 9 - python3.6 10 - python2.7 11 - ruby2.5 12 - java8 13 - dotnetcore2.1 Runtime: 1 Project name [sam-app]: Cloning app templates from https://github.com/awslabs/aws-sam-cli-app-templates.git AWS quick start application templates: 1 - Hello World Example 2 - Step Functions Sample App (Stock Trader) 3 - Quick Start: From Scratch 4 - Quick Start: Scheduled Events 5 - Quick Start: S3 6 - Quick Start: SNS 7 - Quick Start: SQS 8 - Quick Start: Web Backend Template selection: 1 ----------------------- Generating application: ----------------------- Name: sam-app Runtime: nodejs12.x Dependency Manager: npm Application Template: hello-world Output Directory: . Next steps can be found in the README file at ./sam-app/README.md
HTTP APIを作成したいのでファイルを修正します。
template.yaml
というファイルがあるので、そのファイルの22行目をType: HttpApi
に変更します。
33行目の${ServerlessRestApi}
を${ServerlessHttpApi}
に変更します。
$ $ cd sam-app/ ## initを実行してできたディレクトリ $ vi template.yaml ~~~~~~~~ 22 Type: HttpApi 33 Value: !Sub "https://${ServerlessHttpApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/" ~~~~~~~~
sam build
を実行します。
$ sam build Building function 'HelloWorldFunction' Running NodejsNpmBuilder:NpmPack Running NodejsNpmBuilder:CopyNpmrc Running NodejsNpmBuilder:CopySource Running NodejsNpmBuilder:NpmInstall Running NodejsNpmBuilder:CleanUpNpmrc Build Succeeded Built Artifacts : .aws-sam/build Built Template : .aws-sam/build/template.yaml Commands you can use next ========================= [*] Invoke Function: sam local invoke [*] Deploy: sam deploy --guided
sam deploy --guided
を実行してデプロイします
- Stack Name: スタック名
- AWS Region; AWSリージョン
- Confirm changes before deploy: Y
- Allow SAM CLI IAM role creation: Y
- HelloWorldFunction may not have authorization defined, Is this okay?: y
- Save arguments to samconfig.toml: Y
- Deploy this changeset?: y
デプロイが成功すると Successfully ~~~
が表示されます。
$ sam deploy --guided ~~~~~ Successfully created/updated stack - sam-app in ap-northeast-1
AWSのコンソールを確認してみます。
API
Lambda Function
リソースが作成されていることが確認できたので、APIにアクセスしてみます。
$ $ curl https://<your endpoint>/hello {"message":"hello world"}
hello world
というメッセージがjsonで返却されるはずです。
オーソライザーを設定していないため、誰でもアクセスできる状態になっています。
Auth0でAuth0 APIを構築(JWTオーソライザー)
Auth0のダッシュボードにログインし、APIs -> CREATE API
をクリックします
- Name: AWS JWT Authorizer
- Identifier: https://aws-jwt-authorizer
- Signing Algorithm: RS256 (default)
にし、APIを作成します。
HTTP APIにJWTオーソライザーを構成する
/hello
には誰でもアクセスできる状態ですが、承認されたユーザーへのリクエストを制限するようにAPIを構成します。
API Gatewayのコンソールにアクセスし、認可->hello->GET->オーソライザーを作成してアタッチ
をクリックします。
- 名前(オーソライザーの名前):
auth0
- ID ソース:
$request.header.Authorization
- 発行者 URL:
Auth0テナントのURL(https://[YOUR-TENANT-NAME].auth0.com/)
- 対象:
作成したAuth0 APIの識別子 (https://aws-jwt-authorizer)
上記の内容を入力し、アタッチします。
作成されると以下のようになります。
確認してみる
では、この状態で一度APIにアクセスしてみます。
$ curl https://62c3157bka.execute-api.ap-northeast-1.amazonaws.com/hello {"message":"Unauthorized"}
承認ができていないので、Unauthorized
というメッセージが返ってきます。
承認されたユーザーにしかアクセスできないようになりました。
オーソライザーの設定に ID ソース:
$request.header.Authorization` を設定しましたが、
AuthorizationというHeaderにJWTオーソライザーから取得したトークンを付与しないといけません。
Auth0のダッシュボードにいき、作成したAPIのTestタブをクリックします。 そのページにテスト用のトークンが表示されているのでコピーします。
コピーが完了したら、その値を使ってもう一度APIにアクセスします。
$ export ACCESS_TOKEN="<コピーしたトークン>" $ curl \ -H "Authorization: Bearer $ACCESS_TOKEN" \ https://62c3157bka.execute-api.ap-northeast-1.amazonaws.com/hello
トークンの検証が通っていると
{"message":"hello world"}
とメッセージが返ってきます。
これでアクセストークンによる保護ができました。
承認スコープを設定したりしてより細かな保護もできるので是非試してみてください。
まとめ
API GatewayでHTTP APIを構築し、そのAPIに対してAuth0で保護をかけました。 JWTオーソライザーを使用するとエンドポイントへのアクセスを制限できます。
Auth0のようなサービスを使用することにより独自の認証コードを作る必要がなくなるので、よろビジネスロジックに専念できるようになると思います。